/**
 * TDS PEC 4
 * Grupo 3H2M
 *
 * El paquete <code>edu.uoc.tds.pec4.server.bbdd</code> agrupa todas las clases
 * que encapsulan los objetos de acceso a datos (DAO),para realizar el acceso
 * a datos. La base de datos es PostgreSQL.
 */
package edu.uoc.tds.pec4.server.bbdd;

import edu.uoc.tds.pec4.beans.AulaDTO;
import edu.uoc.tds.pec4.beans.CFisicaDTO;
import edu.uoc.tds.pec4.beans.EquipamientoDTO;
import edu.uoc.tds.pec4.beans.EquipamientoSolicitudDTO;
import edu.uoc.tds.pec4.beans.LocalizacionDTO;
import edu.uoc.tds.pec4.beans.ReservaDTO;
import edu.uoc.tds.pec4.beans.SolicitudDTO;
import edu.uoc.tds.pec4.common.util.Constantes;
import edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException;
import edu.uoc.tds.pec4.server.bbdd.exceptions.GestorAulasException;
import java.rmi.RemoteException;
import java.util.List;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

/**
 * La clase <code>SolicitudDAO</code> es el componente de software que suministra
 * la implementación relacionada con la entidad Solicitud y todas sus adyacentes.
 * Principalmente, da servicio a los subsistemas de Conexión y de Aulas.<br />
 * Extiende la clase <code>DataBaseDAO</code><br />
 *
 * @author	Jaime Marcos de la Calle
 * @version	08/12/2011
 * @see         edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException
 */
public class SolicitudDAO extends DataBaseDAO implements ISolicitudDAO{

//    private Connection conexion;
    private PreparedStatement pstmtInsSol;
    private PreparedStatement pstmtInsCFisicas;
    private PreparedStatement pstmtInsEquipamiento;
    private PreparedStatement pstmtInsSolCompleto;
    private PreparedStatement pstmtUpdSol;
    private PreparedStatement pstmtUpdCanSol;
    private PreparedStatement pstmtInsSolCan;
    private PreparedStatement pstmtUpdSolCan;
    private PreparedStatement pstmtInsResCan;
    
   /**
     * Inicializa todas las consultas que se van a disponer en la clase
     * 
     * @throws DataBaseDAOException 
     */
    public SolicitudDAO() throws DataBaseDAOException {
        super();

        pstmtInsSol = super.preparedStatement("INSERT INTO solicitud (tipo,estado, idcliente,idtencuentro,asistentes,superficie,idciudad,"
                    + "fechaini,fechafin,horaini,horafin,diacompleto,observaciones) "
                    + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)RETURNING idsolicitud");
        pstmtInsSolCompleto = super.preparedStatement("INSERT INTO solicitud (tipo,estado, idcliente,idtencuentro,asistentes,superficie,idciudad,"
                    + "fechaini,fechafin,diacompleto,observaciones) "
                    + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)RETURNING idsolicitud");
        pstmtInsCFisicas = super.preparedStatement("INSERT INTO cfisicasolicitud (idsolicitud,idcfisica) "
                + "VALUES (?,?)");
        pstmtInsEquipamiento = super.preparedStatement("INSERT INTO equipamientosolicitud (idsolicitud,idequipamiento,"
                + "cantidad) VALUES (?,?,?)");
        pstmtUpdSol = super.preparedStatement("UPDATE solicitud SET estado =? WHERE idsolicitud =?");
        
        pstmtInsSolCan =super.preparedStatement("INSERT INTO solicitud (tipo, estado, idcliente,idtencuentro,"
                + "asistentes,superficie,idciudad,fechaini,fechafin,horaini,horafin,diacompleto,observaciones)"
                + "select tipo, estado, idcliente,idtencuentro,asistentes,superficie,idciudad,fechaini,fechafin,"
                + "horaini,horafin,diacompleto,observaciones from solicitud where idsolicitud=? "
                + "RETURNING idsolicitud");
        
        pstmtInsResCan =super.preparedStatement("INSERT INTO solicitud (tipo,estado, idcliente,idtencuentro,asistentes,superficie,idciudad,fechaini,"
                + "fechafin,horaini,horafin,diacompleto,observaciones)select tipo,estado, idcliente,idtencuentro,asistentes,superficie,"
                + "idciudad,fechaini,fechafin,horaini,horafin,diacompleto,observaciones from solicitud where idsolicitud=? RETURNING idsolicitud");
        
        pstmtUpdSolCan = super.preparedStatement("UPDATE solicitud set tipo = ? where idsolicitud =?");
        
        pstmtUpdCanSol = super.preparedStatement("UPDATE solicitud set idcancel = ? where idsolicitud =?");
    }
    /**
     * Graba la solicitud del cliente que le viene como parametro en la BBDD
     * 
     * @param solicitud     solicitud del cliente rellenada
     * @param fisicas       caracteristicas fisicas seleccionadas en la solicitud
     * @param equipamiento  equipamiento seleccionado en la solicitud
     * @param cantidad      cantidad del equipamiento seleccionado
     * @throws DataBaseDAOException 
     */
    @Override
    public void grabarSolicitud(SolicitudDTO solicitud, List<CFisicaDTO> fisicas, 
        List<EquipamientoDTO> equipamiento, List<Integer> cantidad) throws DataBaseDAOException {
        
        int contSolicitud = 0;
        if (solicitud == null) {
            throw new DataBaseDAOException(DataBaseDAOException.NO_EXISTE_SOLICITUD);
        }
        try {
            super.setAutoCommit(false);
            pstmtInsSol.clearParameters();
            //comprobamos si la solicitud es de dia completo o no
            if (solicitud.getHoraIni()!=null){
                pstmtInsSol.setInt(1, 1);
                pstmtInsSol.setInt(2, 1);
                pstmtInsSol.setString(3, solicitud.getIdCliente());
                pstmtInsSol.setInt(4, solicitud.getIdTEncuentro());
                pstmtInsSol.setInt(5, solicitud.getAsistentes());
                pstmtInsSol.setDouble(6, solicitud.getSuperficie());
                pstmtInsSol.setInt(7, solicitud.getIdCiudad());
                java.sql.Date sqlDate = new java.sql.Date(solicitud.getFechaIni().getTime());
                pstmtInsSol.setDate(8,sqlDate);
                sqlDate = new java.sql.Date(solicitud.getFechaFin().getTime());
                pstmtInsSol.setDate(9,sqlDate);
                java.sql.Time time = new java.sql.Time(solicitud.getHoraIni().getTime());
                pstmtInsSol.setTime(10,time);
                time = new java.sql.Time(solicitud.getHoraFin().getTime());
                pstmtInsSol.setTime(11,time);
                pstmtInsSol.setBoolean(12, solicitud.getDiaCompleto());
                pstmtInsSol.setString(13, solicitud.getObservaciones());
                ResultSet objRS = pstmtInsSol.executeQuery();
                objRS.next();
                contSolicitud = objRS.getInt(1)-1;
                objRS.close();
            }else{
                pstmtInsSolCompleto.setInt(1, 1);
                pstmtInsSolCompleto.setInt(2, 1);
                pstmtInsSolCompleto.setString(3, solicitud.getIdCliente());
                pstmtInsSolCompleto.setInt(4, solicitud.getIdTEncuentro());
                pstmtInsSolCompleto.setInt(5, solicitud.getAsistentes());
                pstmtInsSolCompleto.setDouble(6, solicitud.getSuperficie());
                pstmtInsSolCompleto.setInt(7, solicitud.getIdCiudad());
                java.sql.Date sqlDate = new java.sql.Date(solicitud.getFechaIni().getTime());
                pstmtInsSolCompleto.setDate(8,sqlDate);
                sqlDate = new java.sql.Date(solicitud.getFechaFin().getTime());
                pstmtInsSolCompleto.setDate(9,sqlDate);
                pstmtInsSolCompleto.setBoolean(10, solicitud.getDiaCompleto());
                pstmtInsSolCompleto.setString(11, solicitud.getObservaciones());
                ResultSet objRS = pstmtInsSolCompleto.executeQuery();
                objRS.next();
                contSolicitud = objRS.getInt(1);
                objRS.close();
            }
            super.commit();
            
        } catch (SQLException eS) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_ALTA_SOLICITUD
                    + Constantes.SL + eS.getMessage());
        } finally {
            super.setAutoCommit(true);
            //insertamos las caracteristicas físicas
            insertarCFisicas(fisicas,contSolicitud);
            insertarEquipamiento(equipamiento,cantidad,contSolicitud);
        }
    }
    /**
     * Se insertan en la BBDD las caraceristicas fisicas requeridas para la actual solicitud
     * @param fisicas           Listado de las caracteristicas fisicas solicitadas
     * @param proxSolicitud     idSolicitud del valor de la solicitud a insertar el listado de las caract. fisicas 
     * @throws DataBaseDAOException 
     */
    private void insertarCFisicas (List <CFisicaDTO> fisicas,int proxSolicitud) throws DataBaseDAOException{
        try {
            int i = 0;
            super.setAutoCommit(false);
            pstmtInsCFisicas.clearParameters();
            while (fisicas.size()>i){
                pstmtInsCFisicas.setInt(1, proxSolicitud);
                pstmtInsCFisicas.setInt(2, fisicas.get(i).getIdCFisica());
                pstmtInsCFisicas.execute();
                i++;
            }
            super.commit();
        } catch (DataBaseDAOException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_INSERTAR_CFISICAS
                    + Constantes.SL + ex.getMessage());
        } catch (SQLException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_INSERTAR_CFISICAS
                    + Constantes.SL + ex.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
    }
    /**
     * Se insertan en la BBDD el equipamiento requeridas para la actual solicitud
     * @param equipamiento      listado del equipamiento solicitado
     * @param cantidad          Cantidad de cada equipamiento solicitado
     * @param proxSolicitud     idSolicitud del valor de la solicitud a insertar el listado de equipamiento 
     * @throws DataBaseDAOException 
     */
    
    private void insertarEquipamiento (List <EquipamientoDTO> equipamiento, List<Integer> cantidad,
            Integer proxSolicitud) throws DataBaseDAOException{
        try {
            int i = 0;
            super.setAutoCommit(false);
            pstmtInsEquipamiento.clearParameters();
            while (equipamiento.size()>i){
                pstmtInsEquipamiento.setInt(1, proxSolicitud);
                pstmtInsEquipamiento.setInt(2, equipamiento.get(i).getIdEquipamiento());
                pstmtInsEquipamiento.setInt(3,cantidad.get(i));
                pstmtInsEquipamiento.execute();
                i++;
            }
            super.commit();
        } catch (DataBaseDAOException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_INSERTAR_EQUIPAMIENTO
                    + Constantes.SL + ex.getMessage());
        } catch (SQLException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_INSERTAR_EQUIPAMIENTO
                    + Constantes.SL + ex.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
    }

     /**
     * Devuelve la lista de Solicitudes que existen actualmente.
     * @return  La lista de todos los Solicitudes de la aplicación
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    @Override
    public List<SolicitudDTO> listaSolicitudes() throws DataBaseDAOException {
        List<SolicitudDTO> solicitudes = new ArrayList<SolicitudDTO>();
        try {
            // Montamos la consulta
            String sSQL = "SELECT idsolicitud,idtipo,observaciones "
                    + " FROM solicitud"
                    + " ORDER BY fechasol";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);

            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                SolicitudDTO inc = new SolicitudDTO();
                inc.setIdSolicitud(objRS.getInt("idsolicitud"));
                inc.setTipo(objRS.getInt("idtipo"));
                inc.setObservaciones(objRS.getString("observaciones"));
                solicitudes.add(inc);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUDES_BBDD
                    + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_GENERAL
                    + Constantes.SL + eE.getMessage());
        }
        return solicitudes;
    }

    /**
     * Devuelve la lista de Solicitudes que existen actualmente.
     * @return  La lista de todos los Solicitudes de la aplicación
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    @Override
    public List<SolicitudDTO> listaSolicitudes(LocalizacionDTO local,
            List<Integer> tiposSol, List<Integer> estados) throws DataBaseDAOException {

        List<SolicitudDTO> solicitudes = new ArrayList<SolicitudDTO>();
        try {
            // Montamos la consulta
            String sSQL = "SELECT s.idSolicitud, s.tipo, s.fechaSol, s.horaSol, s.estado, "
                    + " s.idCliente, s.idtencuentro, s.asistentes, s.fechaini, "
                    + " s.fechafin, s.horaini, s.horafin, s.observaciones, "
                    + " c.nombre as nomciudad, pr.nombre as nomprov, pa.nombre as nompais, "
                    + " us.nombre as nomcliente "
                    + " FROM solicitud s inner join ciudad c"
                    + " on s.idciudad=c.idciudad "
                    + " inner join provincia pr "
                    + " on c.idprovincia=pr.idprovincia "
                    + " inner join pais pa "
                    + " on pr.idpais=pa.idpais"
                    + " inner join usuario us "
                    + " on s.idcliente=us.idusuario"
                    + " WHERE true ";

            if (local != null) {
                if ((local.getPais() != null) && (local.getPais().getIdPais() != Constantes.NO_SELECT)) {
                    sSQL += " AND pa.idpais=" + local.getPais().getIdPais();
                }
                if ((local.getProvincia() != null) && (local.getProvincia().getIdProvincia() != Constantes.NO_SELECT)) {
                    sSQL += " AND pr.idprovincia=" + local.getProvincia().getIdProvincia();
                }
                if ((local.getCiudad() != null) && (local.getCiudad().getIdCiudad() != Constantes.NO_SELECT)) {
                    sSQL += " AND s.idciudad=" + local.getCiudad().getIdCiudad();
                }
            }
            if ((tiposSol != null) && (!tiposSol.isEmpty())) {
                sSQL += " AND s.tipo in (";
                for (int i : tiposSol) {
                    sSQL += i + ",";
                }
                sSQL = sSQL.substring(0, sSQL.length() - 1);
                sSQL += ")";
            }
            if ((estados != null) && (!estados.isEmpty())) {
                sSQL += " AND s.estado in (";
                for (int i : estados) {
                    sSQL += i + ",";
                }
                sSQL = sSQL.substring(0, sSQL.length() - 1);
                sSQL += ")";
            }
            sSQL += " ORDER BY s.fechasol";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);


            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                SolicitudDTO sol = new SolicitudDTO();
                sol.setIdSolicitud(objRS.getInt("idSolicitud"));
                sol.setTipo(objRS.getInt("tipo"));
                sol.setFechaSol(objRS.getDate("fechaSol"));
                sol.setHoraSol(objRS.getTime("horaSol"));
                sol.setEstado(objRS.getInt("estado"));
                sol.setIdCliente(objRS.getString("idCliente"));
                sol.setNomCliente(objRS.getString("nomCliente"));
                sol.setNomCiudad(objRS.getString("nomCiudad"));
                sol.setNomProvincia(objRS.getString("nomProv"));
                sol.setNomPais(objRS.getString("nomPais"));
                solicitudes.add(sol);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUDES_BBDD
                    + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_AULAS_GENERAL
                    + Constantes.SL + eE.getMessage());
        }
        return solicitudes;
    }
    
    /**
     * Devuelve la lista de Solicitudes que existen actualmente del usuario solicitante.
     * @param pais      El país por el que se quiere filtrar
     * @param provincia La provincia por la que se quiere filtrar
     * @param ciudad    La ciudad por la que se quiere filtrar
     * @param tiposSol  Un array con la lista de tipos de solicitudes elegidas
     * @param estado    Integer con el estado de la solicitud
     * @param login     Id del cliente solicitante
     * @return La lista de las solicitudes filtradas por localización, tipos,
     * estados y cliente solicitante
     * @return  La lista de todos los Solicitudes de la aplicación
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    @Override
    public List<SolicitudDTO> listaSolicitudes(LocalizacionDTO local, List<Integer> tiposSol, Integer estado,
    String login) throws DataBaseDAOException {
      List<SolicitudDTO> solicitudes = new ArrayList<SolicitudDTO>();
        try {
            // Montamos la consulta
            String sSQL = "SELECT s.idSolicitud, s.tipo, s.fechaSol, s.horaSol, s.estado, "
                    + " s.idCliente, s.idtencuentro, s.asistentes, s.fechaini, "
                    + " s.fechafin, s.horaini, s.horafin, s.observaciones, "
                    + " c.nombre as nomciudad, pr.nombre as nomprov, pa.nombre as nompais, "
                    + " us.nombre as nomcliente "
                    + " FROM solicitud s inner join ciudad c"
                    + " on s.idciudad=c.idciudad "
                    + " inner join provincia pr "
                    + " on c.idprovincia=pr.idprovincia "
                    + " inner join pais pa "
                    + " on pr.idpais=pa.idpais"
                    + " inner join usuario us "
                    + " on s.idcliente=us.idusuario"
                    + " WHERE s.idCliente='"+login
                    + "' AND s.estado='"+Constantes.SOLICITUD_PENDIENTE+"'"
                    + " AND s.idcancel IS NULL";

            if (local != null) {
                if ((local.getPais() != null) && (local.getPais().getIdPais() != Constantes.NO_SELECT)) {
                    sSQL += " AND pa.idpais=" + local.getPais().getIdPais();
                }
                if ((local.getProvincia() != null) && (local.getProvincia().getIdProvincia() != Constantes.NO_SELECT)) {
                    sSQL += " AND pr.idprovincia=" + local.getProvincia().getIdProvincia();
                }
                if ((local.getCiudad() != null) && (local.getCiudad().getIdCiudad() != Constantes.NO_SELECT)) {
                    sSQL += " AND s.idciudad=" + local.getCiudad().getIdCiudad();
                }
            }
            if ((tiposSol != null) && (!tiposSol.isEmpty())) {
                sSQL += " AND s.tipo in (";
                for (int i : tiposSol) {
                    sSQL += i + ",";
                }
                sSQL = sSQL.substring(0, sSQL.length() - 1);
                sSQL += ")";
            }
            sSQL += " ORDER BY s.fechasol";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);


            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                SolicitudDTO sol = new SolicitudDTO();
                sol.setIdSolicitud(objRS.getInt("idSolicitud"));
                sol.setTipo(objRS.getInt("tipo"));
                sol.setFechaSol(objRS.getDate("fechaSol"));
                sol.setHoraSol(objRS.getTime("horaSol"));
                sol.setEstado(objRS.getInt("estado"));
                sol.setIdCliente(objRS.getString("idCliente"));
                sol.setNomCliente(objRS.getString("nomCliente"));
                sol.setNomCiudad(objRS.getString("nomCiudad"));
                sol.setNomProvincia(objRS.getString("nomProv"));
                sol.setNomPais(objRS.getString("nomPais"));
                solicitudes.add(sol);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUDES_BBDD
                    + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_AULAS_GENERAL
                    + Constantes.SL + eE.getMessage());
        }
        return solicitudes;
    }
    /**
     * Obtiene la solicitud de la que se envía por parámetro su identificador
     * @param idSolicitud      El identificador de solicitud
     * @return La solicitud de la que se quieren obtener todos sus datos
     * @throws RemoteException
     * @throws GestorAulasException
     */
    @Override
    public SolicitudDTO getSolicitud(int idSolicitud) throws DataBaseDAOException {

        SolicitudDTO sol = new SolicitudDTO();
        try {
            // Montamos la consulta
            String sSQL = "SELECT s.idSolicitud, s.tipo, s.estado, s.fechaSol, s.horaSol, "
                    + " s.idCliente, s.idtencuentro, s.asistentes, s.idciudad, s.fechaini, "
                    + " s.fechafin, s.horaini, s.horafin, s.observaciones, s.superficie, s.diacompleto, "
                    + " c.nombre as nomciudad, pr.nombre as nomprov, pa.nombre as nompais, "
                    + " us.nombre as nomcliente, te.nombre as nomtencuentro "
                    + " FROM solicitud s inner join ciudad c"
                    + " on s.idciudad=c.idciudad "
                    + " inner join provincia pr "
                    + " on c.idprovincia=pr.idprovincia "
                    + " inner join pais pa "
                    + " on pr.idpais=pa.idpais"
                    + " inner join usuario us "
                    + " on s.idcliente=us.idusuario"
                    + " inner join tipoencuentro te "
                    + " on s.idtencuentro=te.idtencuentro"
                    + " WHERE s.idsolicitud='"+idSolicitud+"'";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);


            // Recorremos el ResultSet para cargar el objeto DTO
            if (objRS.next()) {
                sol.setIdSolicitud(objRS.getInt("idSolicitud"));
                sol.setTipo(objRS.getInt("tipo"));
                sol.setEstado(objRS.getInt("estado"));
                sol.setFechaSol(objRS.getDate("fechaSol"));
                sol.setHoraSol(objRS.getTime("horaSol"));
                sol.setIdCliente(objRS.getString("idCliente"));
                sol.setIdTEncuentro(objRS.getInt("idtencuentro"));
                sol.setAsistentes(objRS.getInt("asistentes"));
                sol.setIdCiudad(objRS.getInt("idciudad"));
                sol.setFechaIni(objRS.getDate("fechaini"));
                sol.setHoraIni(objRS.getTime("horaini"));
                sol.setFechaFin(objRS.getDate("fechafin"));
                sol.setHoraFin(objRS.getTime("horafin"));
                sol.setObservaciones(objRS.getString("observaciones"));
                sol.setSuperficie(objRS.getDouble("superficie"));
                sol.setDiaCompleto(objRS.getBoolean("diacompleto"));
                sol.setNomCliente(objRS.getString("nomCliente"));
                sol.setNomCiudad(objRS.getString("nomCiudad"));
                sol.setNomProvincia(objRS.getString("nomProv"));
                sol.setNomPais(objRS.getString("nomPais"));
                sol.setNomTEncuentro(objRS.getString("nomtencuentro"));

                // Cargamos las caracterísiticas físicas y equipamientos
                sol.setListCFisicas(getCFisicasSol(idSolicitud));
                sol.setListEquipamiento(getEquipamientoSol(idSolicitud));

            } else {
                // No existe una solicitud con el id pasado
                throw new DataBaseDAOException(DataBaseDAOException.NO_EXISTE_SOLICITUD);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUDES_BBDD
                + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_AULAS_GENERAL
                + Constantes.SL + eE.getMessage());
        }
        return sol;
    }

     /**
     * Cancela la solicitud de la que se envía por parámetro su identificador
     * @param idSolicitud      El identificador de solicitud
     * @return true si fue correcta la eliminacion, false en caso contrario
     * @throws RemoteException
     * @throws GestorConexionException
     */
@Override
    public boolean cancelarSolicitud(int idSolicitud) throws DataBaseDAOException {
        boolean estado = false;
        try {
            super.setAutoCommit(false);
            pstmtInsSolCan.clearParameters();
            pstmtInsSolCan.setInt(1, idSolicitud);
            ResultSet objRS = pstmtInsSolCan.executeQuery();
            objRS.next();
            int i = objRS.getInt(1);
            objRS.close();

            pstmtUpdSolCan.clearParameters();
            pstmtUpdSolCan.setInt(1, Constantes.TIPO_CANCEL_SOLICITUD);
            pstmtUpdSolCan.setInt(2, i);
            pstmtUpdSolCan.execute();

            pstmtUpdCanSol.clearParameters();
            pstmtUpdCanSol.setInt(1, i);
            pstmtUpdCanSol.setInt(2, idSolicitud);
            pstmtUpdCanSol.execute();
            super.commit();
            estado = true;
        } catch (DataBaseDAOException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CANCELAR_SOLICITUD
                + Constantes.SL + ex.getMessage());
        } catch (SQLException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CANCELAR_SOLICITUD
                + Constantes.SL + ex.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
        return estado;
    }  

    /**
     * Cancela la reserva de la que se envía por parámetro su identificador
     * @param idReserva      El identificador de reserva
     * @return true si fue correcta la eliminacion, false en caso contrario
     * @throws RemoteException
     * @throws GestorConexionException
     */
@Override
    public boolean cancelarReserva(int idReserva) throws DataBaseDAOException {
        boolean estado = false;
        try {
            super.setAutoCommit(false);
            pstmtInsResCan.clearParameters();
            pstmtInsResCan.setInt(1, idReserva);
            ResultSet objRS = pstmtInsResCan.executeQuery();
            objRS.next();
            int i = objRS.getInt(1);
            objRS.close();

            pstmtUpdSolCan.clearParameters();
            pstmtUpdSolCan.setInt(1, Constantes.TIPO_CANCEL_RESERVA);
            pstmtUpdSolCan.setInt(2, i); 
            pstmtUpdSolCan.execute();

            pstmtUpdCanSol.clearParameters();
            pstmtUpdCanSol.setInt(1, i);
            pstmtUpdCanSol.setInt(2, idReserva);
            pstmtUpdCanSol.execute();
            super.commit();
            estado = true;
        } catch (DataBaseDAOException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CANCELAR_RESERVA
                + Constantes.SL + ex.getMessage());
        } catch (SQLException ex) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_CANCELAR_RESERVA
                + Constantes.SL + ex.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
        return estado;
    }  

    /**
     * Obtiene la lista de características de una solicitud
     * @param idSolicitud      El identificador de solicitud
     * @return La lista de características físicas de una solicitud
     * @throws DataBaseDAOException
     */
    private List<CFisicaDTO> getCFisicasSol(int idSolicitud) throws DataBaseDAOException {
        List<CFisicaDTO> cfisicas = new ArrayList<CFisicaDTO>();
        try {
            // Montamos la consulta
            String sSQL = "Select cfs.idcfisica, cf.nombre from "
	                + " cfisicasolicitud cfs inner join"
	                + " cfisica cf on cfs.idcfisica=cf.idcfisica"
                        + " where cfs.idsolicitud = " + idSolicitud
	                + " order by nombre";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);

            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                CFisicaDTO sol = new CFisicaDTO();
                sol.setIdCFisica(objRS.getInt("idcfisica"));
                sol.setNomCFisica(objRS.getString("nombre"));
                cfisicas.add(sol);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUD_CFISICAS_BBDD
                + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_AULAS_GENERAL
                + Constantes.SL + eE.getMessage());
        }
        return cfisicas;
    }

    /**
     * Obtiene la lista de equipamientos de una solicitud
     * @param idSolicitud      El identificador de solicitud
     * @return La lista de equipamientos de una solicitud
     * @throws DataBaseDAOException
     */
    private List<EquipamientoSolicitudDTO> getEquipamientoSol(int idSolicitud) throws DataBaseDAOException {
        List<EquipamientoSolicitudDTO> equips = new ArrayList<EquipamientoSolicitudDTO>();
        try {
            // Montamos la consulta
            String sSQL = "Select es.idequipamiento, e.nombre, es.cantidad, e.tipoprecio,"
                        + " e.preciohora, e.preciodia from "
	                + " equipamientosolicitud es inner join"
	                + " equipamiento e on es.idequipamiento=e.idequipamiento"
                    + " where es.idsolicitud = " + idSolicitud
	                + " order by nombre";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);

            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                EquipamientoSolicitudDTO sol = new EquipamientoSolicitudDTO();
                sol.setIdEquipamiento(objRS.getInt("idequipamiento"));
                sol.setNomEquipamiento(objRS.getString("nombre"));
                sol.setCantidad(objRS.getInt("cantidad"));
                sol.setTipoPrecio(objRS.getInt("tipoprecio"));
                sol.setPrecioHora(objRS.getDouble("preciohora"));
                sol.setPrecioDia(objRS.getDouble("preciodia"));
                equips.add(sol);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUD_EQUIPAMIENTOS_BBDD
                + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_GENERAL
                + Constantes.SL + eE.getMessage());
        }
        return equips;
    }

    /**
     * Devuelve la lista de Reservas que existen actualmente del usuario solicitante.
     * @param pais      El país por el que se quiere filtrar
     * @param provincia La provincia por la que se quiere filtrar
     * @param ciudad    La ciudad por la que se quiere filtrar
     * @param tiposRes  Un array con la lista de tipos de solicitudes elegidas
     * @param estado    Integer con el estado de la reserva
     * @param login     Id del cliente solicitante
     * @return La lista de las solicitudes filtradas por localización, tipos,
     * estados y cliente solicitante
     * @return  La lista de todos los Solicitudes de la aplicación
     * @throws  DataBaseDAOException En caso de generarse una excepción de acceso
     *          a la base de datos se dispara al nivel superior
     */
    @Override
    public List<SolicitudDTO> listaReservas(LocalizacionDTO local, List<Integer> tiposRes, Integer estado,
    String login) throws DataBaseDAOException {
      List<SolicitudDTO> solicitudes = new ArrayList<SolicitudDTO>();
        try {
            // Montamos la consulta
            String sSQL = "SELECT s.idSolicitud, s.tipo, s.fechaSol, s.horaSol, s.estado, "
                    + " s.idCliente, s.idtencuentro, s.asistentes, s.fechaini, "
                    + " s.fechafin, s.horaini, s.horafin, s.observaciones, "
                    + " c.nombre as nomciudad, pr.nombre as nomprov, pa.nombre as nompais "
                    + " FROM solicitud s"
                    + " inner join ciudad c"
                    + " on s.idciudad=c.idciudad "
                    + " inner join provincia pr "
                    + " on c.idprovincia=pr.idprovincia "
                    + " inner join pais pa "
                    + " on pr.idpais=pa.idpais"
                    + " WHERE s.idCliente='"+login+ "'"
                    + " AND s.estado='"+Constantes.SOLICITUD_ATENDIDA+"'"
                    + " AND s.idcancel IS NULL";
            
            if (local != null) {
                if ((local.getPais() != null) && (local.getPais().getIdPais() != Constantes.NO_SELECT)) {
                    sSQL += " AND pa.idpais=" + local.getPais().getIdPais();
                }
                if ((local.getProvincia() != null) && (local.getProvincia().getIdProvincia() != Constantes.NO_SELECT)) {
                    sSQL += " AND pr.idprovincia=" + local.getProvincia().getIdProvincia();
                }
                if ((local.getCiudad() != null) && (local.getCiudad().getIdCiudad() != Constantes.NO_SELECT)) {
                    sSQL += " AND s.idciudad=" + local.getCiudad().getIdCiudad();
                }
            }
            if ((tiposRes != null) && (!tiposRes.isEmpty())) {
                sSQL += " AND s.tipo in (";
                for (int i : tiposRes) {
                    sSQL += i + ",";
                }
                sSQL = sSQL.substring(0, sSQL.length() - 1);
                sSQL += ")";
            }
            sSQL += " ORDER BY s.fechasol";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);


            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                SolicitudDTO sol = new SolicitudDTO();
                sol.setIdSolicitud(objRS.getInt("idSolicitud"));
                sol.setTipo(objRS.getInt("tipo"));
                sol.setFechaSol(objRS.getDate("fechaSol"));
                sol.setHoraSol(objRS.getTime("horaSol"));
                sol.setEstado(objRS.getInt("estado"));
                sol.setIdCliente(objRS.getString("idCliente"));
//                sol.setNomCliente(objRS.getString("nomCliente"));
                sol.setNomCiudad(objRS.getString("nomCiudad"));
                sol.setNomProvincia(objRS.getString("nomProv"));
                sol.setNomPais(objRS.getString("nomPais"));
                solicitudes.add(sol);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_SOLICITUDES_BBDD
                    + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_GENERAL
                    + Constantes.SL + eE.getMessage());
        }
        return solicitudes;
    }
    
    @Override
        public List<ReservaDTO> listaReservas(LocalizacionDTO local,
            List<Integer> estados, String fechaDesde, String fechaHasta) throws DataBaseDAOException {

        List<ReservaDTO> reservas = new ArrayList<ReservaDTO>();
        try {
            // Montamos la consulta
            String sSQL = "SELECT r.estado, r.idReserva,s.fechaIni,s.fechaFin"
                    + ",s.idCliente as nomCliente,r.idAula,s.idSolicitud as numSolicitud"
                    + ",r.importe"
                    + " c.nombre as nomciudad, pr.nombre as nomprov, pa.nombre as nompais, "
                    + " us.nombre as nomcliente "
                    + " FROM reserva r inner join solicitud s"
                    + " on r.idReserva=s.idSolicitud "
                    + " inner join ciudad c"
                    + " on s.idciudad=c.idciudad "
                    + " inner join provincia pr "
                    + " on c.idprovincia=pr.idprovincia "
                    + " inner join pais pa "
                    + " on pr.idpais=pa.idpais"
                    + " inner join usuario us "
                    + " on s.idCliente=us.idUsuario"
                    + " WHERE (s.fechaIni BETWEEN fechaDesde AND fechaHasta) AND"
                    + " (s.fechaFin BETWEEN fechaDesde AND fechaHasta)";


            if (local != null) {
                if ((local.getPais() != null) && (local.getPais().getIdPais() != Constantes.NO_SELECT)) {
                    sSQL += " AND pa.idpais=" + local.getPais().getIdPais();
                }
                if ((local.getProvincia() != null) && (local.getProvincia().getIdProvincia() != Constantes.NO_SELECT)) {
                    sSQL += " AND pr.idprovincia=" + local.getProvincia().getIdProvincia();
                }
                if ((local.getCiudad() != null) && (local.getCiudad().getIdCiudad() != Constantes.NO_SELECT)) {
                    sSQL += " AND s.idciudad=" + local.getCiudad().getIdCiudad();
                }
            }

            if ((estados != null) && (!estados.isEmpty())) {
                sSQL += " AND s.estado in (";
                for (int i : estados) {
                    sSQL += i + ",";
                }
                sSQL = sSQL.substring(0, sSQL.length() - 1);
                sSQL += ")";
            }
            sSQL += " ORDER BY s.fechasol";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);


            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                ReservaDTO res = new ReservaDTO();
                res.setEstado(objRS.getInt("estado"));
                res.setIdAula(objRS.getInt("idReserva"));
                res.setFechaDesde(objRS.getDate("fechaDesde"));
                res.setFechaHasta(objRS.getDate("fechaHasta"));
                res.setNomCliente(objRS.getString("nomCliente"));
                res.setIdAula(objRS.getInt("idAula"));
                res.setNumSolicitud(objRS.getInt("numSolicitud"));
                res.setImporte(objRS.getDouble("importe"));
                reservas.add(res);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_RESERVAS_BBDD
                    + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_GENERAL
                    + Constantes.SL + eE.getMessage());
        }
        return reservas;
    }

   public List<AulaDTO> listaAulas(LocalizacionDTO local,
             List<Integer> estados,String fechaDesde, String fechaHasta) throws DataBaseDAOException {

        List<AulaDTO> aulas = new ArrayList<AulaDTO>();
        try {
            // Montamos la consulta

            String sSQL = "SELECT a.idAula, a.nombre, a.direccion, a.superficie, "
                    + " a.aforo "
                    + " r.fechaini,r.fechafin"
                    + " c.nombre as nomciudad, pr.nombre as nomprov, pa.nombre as nompais, "
                    + " FROM reserva r inner join ciudad c"
                    + " on a.idciudad=c.idciudad "
                    + " inner join provincia pr "
                    + " on c.idprovincia=pr.idprovincia "
                    + " inner join pais pa "
                    + " on pr.idpais=pa.idpais"
                    + " inner join reserva r "
                    + " on a.idAula=r.idAula"
                    + " WHERE (r.fechaIni BETWEEN fechaDesde AND fechaHasta) AND"
                    + " (r.fechaFin BETWEEN fechaDesde AND fechaHasta) OR true ";

            if (local != null) {
                if ((local.getPais() != null) && (local.getPais().getIdPais() != Constantes.NO_SELECT)) {
                    sSQL += " AND pa.idpais=" + local.getPais().getIdPais();
                }
                if ((local.getProvincia() != null) && (local.getProvincia().getIdProvincia() != Constantes.NO_SELECT)) {
                    sSQL += " AND pr.idprovincia=" + local.getProvincia().getIdProvincia();
                }
                if ((local.getCiudad() != null) && (local.getCiudad().getIdCiudad() != Constantes.NO_SELECT)) {
                    sSQL += " AND s.idciudad=" + local.getCiudad().getIdCiudad();
                }
            }

            if ((estados != null) && (!estados.isEmpty())) {
                sSQL += " AND s.estado in (";
                for (int i : estados) {
                    sSQL += i + ",";
                }
                sSQL = sSQL.substring(0, sSQL.length() - 1);
                sSQL += ")";
            }
            sSQL += " ORDER BY a.idAula";

            // Lanzamos la consulta contra la BBDD
            ResultSet objRS = super.obtenerConsulta(sSQL);

            // Recorremos el ResultSet para cargar el vector
            while (objRS.next()) {
                AulaDTO aula = new AulaDTO();
                aula.setNomPais(objRS.getString("nomPais"));
                aula.setNomCiudad(objRS.getString("nomCiudad"));
                aula.setDireccion(objRS.getString("direccion"));
                aula.setSuperficie(objRS.getDouble("superficie"));
                aula.setAforo(objRS.getInt("aforo"));
                //fecha desde y fecha hasta
                aulas.add(aula);
            }

            // Liberamos recursos
            objRS.close();
            objRS = null;

        } catch (SQLException eS) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_LEER_AULAS_BBDD
                    + Constantes.SL + eS.getMessage());
        } catch (Exception eE) {
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_MAESTROS_GENERAL
                    + Constantes.SL + eE.getMessage());
        }
        return aulas;
    }

    @Override
    public List<ReservaDTO> listaReservas() throws DataBaseDAOException {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    public void insertarSolicitud(SolicitudDTO solicitud) throws DataBaseDAOException {
        if (solicitud == null) {
            throw new DataBaseDAOException(DataBaseDAOException.SOLICITUD_NULA);
        }
        
        try {
            pstmtUpdSol = super.preparedStatement("UPDATE solicitud set estado=? where idsolicitud=?");
            
            // Envolvemos la secuencia de inserts dentro de una transacción
            super.setAutoCommit(false);
            
            // Cambiamos el estado de la solicitud a atendida
            pstmtUpdSol.setInt(1, solicitud.getEstado());
            pstmtUpdSol.setInt(2, solicitud.getIdSolicitud());
            pstmtUpdSol.execute();
            
            super.commit();

            pstmtUpdSol.close();

        } catch (SQLException eS) {
            super.rollback();
            throw new DataBaseDAOException(DataBaseDAOException.ERROR_ALTA_RESERVA
                    + Constantes.SL + eS.getMessage());
        } finally {
            super.setAutoCommit(true);
        }
    }    
}

